package v1

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"strconv"
	"time"
	"web_framework/config"
	"web_framework/model"
	"web_framework/pkg/constvar"
	. "web_framework/pkg/e"
	"web_framework/pkg/errno"
	"web_framework/router/api"
	"web_framework/router/middleware"
	"web_framework/service"
	"web_framework/storage"
	"web_framework/websocket/v1/handler"
)

type ResourceAPI struct {
}

func (a ResourceAPI) Name() string {
	return "resource API"
}

func (a ResourceAPI) Bind() {
	resourceAPI := config.C.Router.Group("/api/v1/data", middleware.TrackLog())
	{
		resourceAPI.GET("resource/search", Search)
		resourceAPI.GET("resource/resource_detail", ResourceDetail)
		resourceAPI.GET("resource/test", SearchTestCloud)
		resourceAPI.GET("resource/test_local", SearchTestLocal)
	}
}


// 3.1 搜索接口
func Search(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"keyword","sn","uid","token","sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	sn := params["sn"]
	var data model.SearchReturn
	var pathCacheKey string // defaultPath, 默认目录供websocket调用使用
	pathCacheKey = constvar.RouterRedisPrefix + sn + constvar.RedisStorageDownloadPath
	data.LocalData = nil

	// 搜索本地资源
	bo, _ := storage.RedisHExists(pathCacheKey, "path")
	if bo {
		// 推送到 下载模块
		mid, getMidErr := service.GenMid(params["sn"])
		if getMidErr != nil {
			api.SendResponse(c, getMidErr, nil)
			return
		}

		path, _ := storage.RedisHGet(pathCacheKey, "path")
		var returnData interface{} = model.ResponseData{
			Path:    path,
			Keyword: params["keyword"],
		}
		requestMsg := model.Response{
			Mid:   mid,
			Mtype: constvar.MTypeGetSearchLocalRequest,
			Time:  time.Now().Unix(),
			Data:  &returnData,
		}
		client := []string{params["sn"]}
		errSend := handler.WriteMessage(client, requestMsg)
		if errSend != nil {
			api.SendResponse(c, errno.ErrSearchLoacl, nil)
			return
		}
		searchCacheKey := constvar.RouterRedisPrefix + sn + constvar.RedisSearchLocalMidCacheKey + ":" + strconv.Itoa(mid)
		Log("Info", "搜索Key为 ", searchCacheKey)
		if bo,_ := storage.RedisSet(searchCacheKey, 1 , 20);bo == false{
			Log("Info", "更新搜索本地资源缓存标记失败")
		}

		// 轮训3秒
		for a := 0; a < constvar.TimeFormatSecond * 3; a++ {
			time.Sleep(time.Duration(1) * time.Second)
			fileCache, err := storage.RedisGet(searchCacheKey)
			if err != nil || fileCache == "1"{
				Log("Info", "读取更新速度限制缓存标记失败")
				continue
			}
			cacheDoneKey := constvar.RouterRedisPrefix + sn + constvar.RedisSearchLocalFilesDoneCacheKey
			if storage.RedisExists(cacheDoneKey) {
				isDone, _ := storage.RedisGet(cacheDoneKey)
				if isDone == "1" {
					break
				}
			}
		}
		data.LocalData, _ = GetSearchDataFromCache(sn, params["keyword"])
	}else {
		Log("Info", "该路由器[", sn, "]没有外接存储，搜索本地资源为空")
	}

	// 搜索云端资源
	var uid, token string
	if config.C.RunMode == "debug" {
		uid = "6281359"
		token = "4ef6f285060e2ca1001b034d72df361d"
	}else {
		uid = params["uid"]
		token = params["token"]
	}
	keyword := params["keyword"]
	page := 1
	cloudData, err := service.ResourceCloudSearch(uid, token, keyword, page)
	if err != nil {
		api.SendResponse(c, errno.ErrValidation, nil)
		return
	}
	data.CloudData = cloudData

	errno.OK.Info = "搜索成功"
	api.SendResponse(c, errno.OK, data)
	return
}

// 取缓存中的回调数据
func GetSearchDataFromCache(sn, keyword string) (re []model.ResourceSearch, err error) {

	var searchLen string
	cacheLenKey := constvar.RouterRedisPrefix + sn + constvar.RedisSearchLocalFilesPageCacheKey
	searchLen, err = storage.RedisGet(cacheLenKey)
	if err == nil {
		length, _ := strconv.Atoi(searchLen)
		for j:=1; j <= length; j++ {
			cacheKey := constvar.RouterRedisPrefix + sn + constvar.RedisSearchLocalFilesCacheKey + ":flies:" + Md5Str(keyword) + ":" + strconv.Itoa(j)
			Log("Warn", "[Key] ", cacheKey)
			searchLocalData, err := storage.RedisGet(cacheKey)
			if err != nil {
				continue
			}
			Log("Warn", "[Searched Data] ", searchLocalData)
			err = json.Unmarshal([]byte(searchLocalData), &re)
			if err != nil {
				return re, err
			}
		}
	}

	return re, nil
}



// 3.4 资源详情
func ResourceDetail(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid","token","rid","sver","client"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var uid, token string
	if config.C.RunMode == "debug" {
		uid = "6281359"
		token = "4ef6f285060e2ca1001b034d72df361d"
	}else {
		uid = params["uid"]
		token = params["token"]
	}
	data, err := service.HttpSearchResourceDetail(params["rid"], uid, token, params["client"])
	if err != nil {
		api.SendResponse(c, errno.ErrResourceDetail, nil)
		return
	}

	if data.List == nil {
		api.SendResponse(c, errno.ErrResourceNotFound, nil)
		return
	}

	errno.OK.Info = "资源详情获取成功"
	api.SendResponse(c, errno.OK, data)
	return
}

func SearchTestCloud(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid","token"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var uid, token string
	if config.C.RunMode == "debug" {
		uid = "6281359"
		token = "4ef6f285060e2ca1001b034d72df361d"
	}else {
		uid = params["uid"]
		token = params["token"]
	}
	keyword := params["keyword"]
	page := 1
	data, err := service.ResourceCloudSearch(uid, token, keyword, page)
	if err != nil {
		api.SendResponse(c, errno.ErrValidation, nil)
		return
	}

	errno.OK.Info = "云端搜索成功"
	api.SendResponse(c, errno.OK, data)
	return
}

func SearchTestLocal(c *gin.Context) {

	var a float64
	a = 0.25
	api.SendResponse(c, errno.OK, strconv.FormatFloat(a, 'f', 2, 64))
	return
}